<?php

namespace Kunfeng\Dify\Client\Impl;

use GuzzleHttp\Client;
use Kunfeng\Dify\Client\DifyDatasetsClientInterface;
use Kunfeng\Dify\Constants\ApiPaths;
use Kunfeng\Dify\Exception\DifyApiException;
use Kunfeng\Dify\Model\Datasets\CreateDatasetRequest;
use Kunfeng\Dify\Model\Datasets\Dataset;
use Kunfeng\Dify\Model\Datasets\DatasetListResponse;
use Kunfeng\Dify\Model\Datasets\CreateDocumentRequest;
use Kunfeng\Dify\Model\Datasets\Document;
use Kunfeng\Dify\Model\Datasets\DocumentListResponse;
use Kunfeng\Dify\Model\Datasets\RetrieveRequest;
use Kunfeng\Dify\Model\Datasets\RetrieveResponse;
use Kunfeng\Dify\Model\Datasets\Segment;
use Kunfeng\Dify\Model\Datasets\SegmentListResponse;
use Kunfeng\Dify\Model\Datasets\UpdateSegmentRequest;
use Kunfeng\Dify\Model\Common\SimpleResponse;
use Kunfeng\Dify\Model\File\FileUploadRequest;
use Kunfeng\Dify\Model\File\FileUploadResponse;
use Kunfeng\Dify\Model\File\FilePreviewResponse;
use Kunfeng\Dify\Model\Chat\AppInfoResponse;
use Kunfeng\Dify\Model\Chat\AppParametersResponse;
use Kunfeng\Dify\Model\Chat\AppWebAppSettingResponse;

/**
 * Dify 知识库管理客户端实现
 */
class DifyDatasetsClient extends AbstractDifyClient implements DifyDatasetsClientInterface
{
    public function __construct(string $baseUrl, string $apiKey, $httpClient = null, $retryHandler = null)
    {
        parent::__construct($baseUrl, $apiKey, $httpClient, $retryHandler);
    }

    /**
     * 创建知识库
     */
    public function createDataset(CreateDatasetRequest $request): Dataset
    {
        $data = $this->executePost(ApiPaths::DATASETS, $request->toArray());
        return Dataset::fromArray($data);
    }

    /**
     * 获取知识库列表
     */
    public function getDatasets(int $page = 1, int $limit = 20): DatasetListResponse
    {
        $data = $this->executeGet(ApiPaths::DATASETS, [
            'page' => $page,
            'limit' => $limit
        ]);
        return DatasetListResponse::fromArray($data);
    }

    /**
     * 获取知识库详情
     */
    public function getDataset(string $datasetId): Dataset
    {
        $data = $this->executeGet(ApiPaths::DATASETS . '/' . $datasetId);
        return Dataset::fromArray($data);
    }

    /**
     * 更新知识库
     */
    public function updateDataset(string $datasetId, array $data): Dataset
    {
        $response = $this->executePut(ApiPaths::DATASETS . '/' . $datasetId, $data);
        return Dataset::fromArray($response);
    }

    /**
     * 删除知识库
     */
    public function deleteDataset(string $datasetId): SimpleResponse
    {
        $data = $this->executeDelete(ApiPaths::DATASETS . '/' . $datasetId);
        return SimpleResponse::fromArray($data);
    }

    /**
     * 创建文档
     */
    public function createDocument(string $datasetId, CreateDocumentRequest $request): Document
    {
        $path = ApiPaths::getDatasetDocumentsPath($datasetId);
        $data = $this->executePost($path, $request->toArray());
        return Document::fromArray($data);
    }

    /**
     * 获取文档列表
     */
    public function getDocuments(string $datasetId, int $page = 1, int $limit = 20): DocumentListResponse
    {
        $path = ApiPaths::getDatasetDocumentsPath($datasetId);
        $data = $this->executeGet($path, [
            'page' => $page,
            'limit' => $limit
        ]);
        return DocumentListResponse::fromArray($data);
    }

    /**
     * 获取文档详情
     */
    public function getDocument(string $datasetId, string $documentId): Document
    {
        $path = ApiPaths::getDatasetDocumentsPath($datasetId) . '/' . $documentId;
        $data = $this->executeGet($path);
        return Document::fromArray($data);
    }

    /**
     * 更新文档
     */
    public function updateDocument(string $datasetId, string $documentId, array $data): Document
    {
        $path = ApiPaths::getDatasetDocumentsPath($datasetId) . '/' . $documentId;
        $response = $this->executePut($path, $data);
        return Document::fromArray($response);
    }

    /**
     * 删除文档
     */
    public function deleteDocument(string $datasetId, string $documentId): SimpleResponse
    {
        $path = ApiPaths::getDatasetDocumentsPath($datasetId) . '/' . $documentId;
        $data = $this->executeDelete($path);
        return SimpleResponse::fromArray($data);
    }

    /**
     * 语义检索
     */
    public function retrieve(RetrieveRequest $request): RetrieveResponse
    {
        // 这里需要从请求中获取 datasetId，但 RetrieveRequest 中没有
        // 需要修改 RetrieveRequest 来包含 datasetId
        throw new \BadMethodCallException('Retrieve method requires datasetId parameter');
    }

    /**
     * 语义检索（带数据集ID）
     */
    public function retrieveFromDataset(string $datasetId, RetrieveRequest $request): RetrieveResponse
    {
        $path = ApiPaths::getDatasetRetrievePath($datasetId);
        $data = $this->executePost($path, $request->toArray());
        return RetrieveResponse::fromArray($data);
    }

    /**
     * 上传文件
     */
    public function uploadFile($fileOrRequest, $filePathOrStream, ?string $user = null): FileUploadResponse
    {
        return parent::uploadFile($fileOrRequest, $filePathOrStream, $user);
    }

    /**
     * 获取应用信息
     */
    public function getAppInfo(): AppInfoResponse
    {
        $data = $this->executeGet(ApiPaths::META);
        return AppInfoResponse::fromArray($data);
    }

    /**
     * 获取应用参数
     */
    public function getAppParameters(): AppParametersResponse
    {
        $data = $this->executeGet(ApiPaths::META . '/parameters');
        return AppParametersResponse::fromArray($data);
    }

    /**
     * 获取应用 WebApp 设置
     */
    public function getAppWebAppSettings(): AppWebAppSettingResponse
    {
        $data = $this->executeGet(ApiPaths::META . '/webapp-settings');
        return AppWebAppSettingResponse::fromArray($data);
    }

    /**
     * 预览文件
     */
    public function previewFile(string $fileId, bool $asAttachment = false): FilePreviewResponse
    {
        $data = $this->executeGet(ApiPaths::FILES_PREVIEW . '/' . $fileId, [
            'as_attachment' => $asAttachment
        ]);
        return FilePreviewResponse::fromArray($data);
    }

    /**
     * 获取文档分段列表
     */
    public function getSegments(string $datasetId, string $documentId, ?int $page = null, ?int $limit = null): SegmentListResponse
    {
        $query = [];
        if ($page !== null) {
            $query['page'] = $page;
        }
        if ($limit !== null) {
            $query['limit'] = $limit;
        }

        $path = ApiPaths::getDocumentSegmentsPath($datasetId, $documentId);
        $data = $this->executeGet($path, $query);
        return SegmentListResponse::fromArray($data);
    }

    /**
     * 获取分段详情
     */
    public function getSegment(string $datasetId, string $documentId, string $segmentId): Segment
    {
        $path = ApiPaths::getDocumentSegmentPath($datasetId, $documentId, $segmentId);
        $data = $this->executeGet($path);
        return Segment::fromArray($data);
    }

    /**
     * 更新分段
     */
    public function updateSegment(string $datasetId, string $documentId, string $segmentId, UpdateSegmentRequest $request): Segment
    {
        $path = ApiPaths::getDocumentSegmentPath($datasetId, $documentId, $segmentId);
        $data = $this->executePut($path, $request->toArray());
        return Segment::fromArray($data);
    }

    /**
     * 删除分段
     */
    public function deleteSegment(string $datasetId, string $documentId, string $segmentId): SimpleResponse
    {
        $path = ApiPaths::getDocumentSegmentPath($datasetId, $documentId, $segmentId);
        $data = $this->executeDelete($path);
        return SimpleResponse::fromArray($data);
    }

    /**
     * 启用分段
     */
    public function enableSegment(string $datasetId, string $documentId, string $segmentId): SimpleResponse
    {
        $path = ApiPaths::getDocumentSegmentPath($datasetId, $documentId, $segmentId) . '/enable';
        $data = $this->executePost($path);
        return SimpleResponse::fromArray($data);
    }

    /**
     * 禁用分段
     */
    public function disableSegment(string $datasetId, string $documentId, string $segmentId): SimpleResponse
    {
        $path = ApiPaths::getDocumentSegmentPath($datasetId, $documentId, $segmentId) . '/disable';
        $data = $this->executePost($path);
        return SimpleResponse::fromArray($data);
    }
}
